home *** CD-ROM | disk | FTP | other *** search
/ Scena PL EXE / scenapl-1995-exe.iso / torba szopy / gry / uchess / search.c < prev    next >
C/C++ Source or Header  |  1995-10-19  |  51KB  |  1,883 lines

  1. /*
  2.  * search.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  5.  * Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify it under
  10.  * the terms of the GNU General Public License as published by the Free
  11.  * Software Foundation; either version 2, or (at your option) any later
  12.  * version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  15.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  17.  * details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License along with
  20.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  21.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23. #include "gnuchess.h"
  24.  
  25. #define ZEROALLBETWEENPLY 1
  26.  
  27. #ifdef QUIETBACKGROUND
  28. short __aligned background = 0;
  29.  
  30. #endif /* QUIETBACKGROUND */
  31. static short int __aligned DepthBeyond;
  32. short __aligned Threat[MAXDEPTH];
  33. unsigned short int __aligned PrVar[MAXDEPTH];
  34. extern short int ISZERO;
  35. extern long EADD,EGET;
  36. extern char mvstr[4][6];
  37. extern short int recycle;
  38. extern int trying_again;
  39. short int __aligned myflagdeepnull=0xff;
  40. int got_20000=0;
  41. short __aligned ThreatSave[MAXDEPTH]; /* tom@izf.tno.nl */
  42. extern short __aligned QueenCheck[MAXDEPTH]; /* tom@izf.tno.nl */
  43. #if defined NULLMOVE || defined DEEPNULL
  44. short int __aligned no_null;
  45. short int __aligned null;         /* Null-move already made or not */
  46. short int __aligned PVari;        /* Is this the PV */
  47. #endif
  48. #ifdef DEBUG40
  49. extern int whichway;
  50. #endif
  51. #ifdef DEBUG
  52. unsigned short __aligned DBLINE[MAXDEPTH];
  53. struct leaf __aligned *dbptr;
  54.  
  55. #endif
  56. short __aligned start_stage;
  57. short __aligned thrashing_tt; /* must we recycle slots at random. TomV */
  58. short int __aligned zwndw;
  59.  
  60. #include "ataks3.h"
  61.  
  62. #define __USE_SYSBASE
  63. #include <proto/exec.h>
  64.  
  65. extern long OrigResponse;
  66. extern int global_tmp_score;
  67. extern int previous_score;
  68. short __aligned myflagpvs=true;
  69. int __aligned backsrchaborted=0;
  70. int __aligned Sdepth2=0;
  71. extern int MoveNowOK;
  72. extern int procpri;
  73. extern struct Process *myproc;
  74.  
  75.  
  76. #ifdef SPEED_PRECALC
  77. unsigned short __aligned PreCalcedHint;
  78. unsigned short __aligned PreCalcedMove;
  79. int DoPreCalc (unsigned INTSIZE *, INTSIZE);
  80. #endif
  81. int __aligned Castled[2]={0,0};
  82. int __aligned myEnPassant[2]={0,0};
  83.  
  84.  
  85.  
  86. inline short int repetition (void);
  87.  
  88.  
  89. #include "debug41.h"
  90. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  91.  
  92. #ifndef STRAIGHT4PL68
  93. // improved Kong Sian Repetition
  94.  
  95. inline
  96. short int
  97. repetition ()
  98.  
  99. /*  Check for draw by threefold repetition.  */
  100.  
  101. {
  102.   register short i, cnt;
  103.  
  104.   cnt = 0;
  105.   /* try to avoid work */
  106.   if (GameCnt > Game50 + 3)
  107.     for (i = GameCnt; i >= Game50; i--)
  108.       if (hashbd == GameList[i].hashbd && hashkey == GameList[i].hashkey)
  109.         cnt++;
  110.  
  111.   return cnt;
  112. }
  113.  
  114. #else // straight 4pl68 repetition
  115. inline
  116. short int
  117. repetition ()
  118.  
  119. /*  Check for draw by threefold repetition.  */
  120.  
  121. {
  122.   register short i, c,cnt;
  123.   register unsigned short m;
  124.   short b[64];
  125.  
  126.   cnt = c = 0;
  127.   /* try to avoid work */
  128.   if (GameCnt > Game50 + 3) // changed from gamecnt+4
  129.     {
  130. #if defined(NOMEMSET) || defined(MSDOS)
  131.       for (i = 0; i < 64; b[i++] = 0);
  132. #else
  133. #ifndef AMIGA
  134.       memset ((char *) b, 0, (unsigned long)sizeof (b));
  135. #else
  136.       ClearMem(b,sizeof (b));
  137. #endif
  138. #endif /* NOMEMSET */
  139.       for (i = GameCnt; i >= Game50; i--)
  140.     {
  141.       m = GameList[i].gmove;
  142.       /* does piece exist on diff board? */
  143.       if (b[m & 0x3f])
  144.         {
  145.           /* does diffs cancel out, piece back? */
  146.           if ((b[m >> 8] += b[m & 0x3f]) == 0)
  147.         --c;
  148.           b[m & 0x3f] = 0;
  149.         }
  150.       else
  151.         {
  152.           /* create diff */
  153.           ++c;
  154.           /* does diff cancel out another diff? */
  155.           if (!(b[m >> 8] -= (b[m & 0x3f] = board[m & 0x3f] +
  156.                   (color[m & 0x3f] << 8))))
  157.         --c;
  158.         }
  159.       /* if diff count is 0 we have a repetition */
  160.       if (c == 0)
  161.         if ((i ^ GameCnt) & 1)
  162.           cnt++;
  163.     }
  164.     }
  165.     return cnt;
  166. }
  167. #endif // striaght 4pl68 repetition
  168.  
  169. int plyscore, globalscore;
  170. int
  171. pick (short int p1, short int p2)
  172.  
  173. /*
  174.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  175.  * move into the p1 element.
  176.  *
  177.  */
  178. {
  179.   register struct leaf *p, *q, *r, *k;
  180.   register s0;
  181.   struct leaf temp;
  182.  
  183.   k = p = &Tree[p1];
  184.   q = &Tree[p2];
  185.   s0 = p->score;
  186.   for (r = p + 1; r <= q; r++)
  187.     if ((r->score) > s0)
  188.       {
  189.     s0 = (r->score);
  190.     p = r;
  191.       }
  192.   if (p != k)
  193.     {
  194.       temp = *p;
  195.       *p = *k;
  196.       *k = temp;
  197.       return true;
  198.     }
  199.   return false;
  200. }
  201.  
  202. #ifdef DEBUG
  203. unsigned short trace[MAXDEPTH];
  204. char traceline[256];
  205. unsigned short tracelog[MAXDEPTH];
  206. int tracen = 0;
  207. int traceflag = 0;
  208. int traceply = 0;
  209. #endif
  210. int __aligned bookflag = false;
  211. int __aligned Jscore = 0;
  212.  
  213. static int __aligned TCcount, TCleft;
  214. void
  215. SelectMove (short int side, short int iop)
  216.  
  217.  
  218. /*
  219.  * Select a move by calling function search() at progressively deeper ply
  220.  * until time is up or a mate or draw is reached. An alpha-beta window of
  221.  * -Awindow to +Bwindow points is set around the score returned from the
  222.  * previous iteration. If Sdepth != 0 then the program has correctly
  223.  * predicted the opponents move and the search will start at a depth of
  224.  * Sdepth+1 rather than a depth of 1.
  225.  */
  226.  
  227. {
  228.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  229.   static short int alpha, beta, score;
  230.   static struct GameRec *g;
  231.   int earlyflag;
  232.   char mystr[16];
  233.   short InChkDummy;
  234.   short start_score;
  235. #ifdef DEBUG
  236.  
  237. if(debuglevel & (512|1024)){
  238.     char b[32];
  239.     short c1,c2,r1,r2;
  240. tracen=0;
  241. traceflag = false;
  242. traceply = 0;
  243. tracelog[0]=0;
  244. while(true){
  245.     /*printf("debug?");
  246.     gets(b);*/
  247.     if(b[0] == 'p')traceply = atoi(&b[1]);
  248.     else
  249.     if(b[0] == '\0')break;
  250.     else{
  251.         c1 = b[0] - 'a';
  252.               r1 = b[1] - '1';
  253.               c2 = b[2] - 'a';
  254.               r2 = b[3] - '1';
  255.               trace[++tracen] = (locn (r1, c1) << 8) | locn (r2, c2);
  256.     }
  257.     if(tracen == 0 && traceply >0)traceflag = true;
  258.     }
  259.     
  260. }
  261. #endif
  262.  
  263. //  InitializeStats(); // MY FIX FOR UNDO PROBLEMS!!! TMP!!!
  264.  
  265. got_20000 = 0;
  266. start_again:
  267.   flag.timeout = false;
  268.   flag.back = flag.musttimeout = false;
  269.   xside = side ^ 1;
  270.   recycle = (GameCnt % rehash) - rehash;
  271.   /* if background mode set to infinite */
  272.   if (iop == 2)
  273.     {
  274.       (void)SetTaskPri((struct Task *)myproc,0);
  275.       OrigResponse = ResponseTime = 9999999;
  276. #ifdef QUIETBACKGROUND
  277.       background = true;
  278. #endif /* QUIETBACKGROUND */
  279.     }
  280.   else
  281.     {
  282.       player = side;
  283.       if (TCflag)
  284.     {
  285.       TCcount = 0;
  286. #ifdef QUIETBACKGROUND
  287.       background = false;
  288. #endif /* QUIETBACKGROUND */
  289.       if (TimeControl.moves[side] < 1)
  290.         TimeControl.moves[side] = 1;
  291.       /* special case time per move specified */
  292.       if (flag.onemove)
  293.         {
  294.           OrigResponse = ResponseTime = TimeControl.clock[side] - 100;
  295.           TCleft = 0;
  296.         }
  297.       else
  298.         {
  299.           /* calculate avg time per move remaining */
  300.           TimeControl.clock[side] += TCadd;
  301.  
  302.           ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
  303.           TCleft = (int)ResponseTime / 3;
  304.           ResponseTime += TCadd/2;
  305.           if (TimeControl.moves[side] < 5)
  306.         TCcount = MAXTCCOUNTX - 1;
  307.         }
  308.       if (ResponseTime < 101)
  309.         {
  310.           ResponseTime = 100;
  311.           TCcount = MAXTCCOUNTX;
  312.         }
  313.       else if (ResponseTime < 200)
  314.         {
  315.           TCcount = MAXTCCOUNTX - 1;
  316.         }
  317.           OrigResponse = ResponseTime;
  318.           if ((TimeControl.moves[side] > 9))
  319.            ResponseTime += 51;
  320. //           ResponseTime = ResponseTime + (ResponseTime/4); // ADDED TO 2.50 to make clock better
  321.     }
  322.       else
  323.        {
  324. #ifdef QUIETBACKGROUND
  325.       background = false;
  326. #endif /* QUIETBACKGROUND */
  327.     OrigResponse = ResponseTime = MaxResponseTime;
  328.        }
  329.       if (TCleft)
  330.     {
  331.       TCcount = ((int)((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
  332.       if (TCcount > MAXTCCOUNTX)
  333.         TCcount = 0;
  334.       else
  335.         TCcount = MAXTCCOUNTX - TCcount;
  336.     }
  337.       else
  338.     TCcount = MAXTCCOUNTX;
  339.     }
  340.  
  341.   if (MoveNowOK)
  342.    {
  343.     thinking2 = 1; /* allow move now menu item to work */
  344.    }
  345.   else
  346.    {
  347.     thinking2 = 0; /* do not allow move now menu item to work */
  348.    }
  349. #ifndef OLD_LOOKAHEAD // this is faster for predicted moves
  350. //sprintf(mystr,"sd2 %d",Sdepth);
  351. //ShowMessage(mystr);
  352.   if (Sdepth > 0) // guessed correct move!
  353.    {
  354.      if (TCflag)
  355.        time0 = time(0L);
  356. #ifdef QUIETBACKGROUND
  357.     if (!background)
  358. #endif /* QUIETBACKGROUND */
  359.      SearchStartStuff (side);
  360.     trying_again = 0;
  361.     if ((GameCnt>2)&&(TCflag)&&(global_tmp_score >= (previous_score-50))&&(Sdepth >= GlobalTgtDepth)
  362.           &&(global_tmp_score >= (GameList[GameCnt-1].score - 50)))
  363.      {
  364.       if (Sdepth >= (GameList[GameCnt-1].depth))
  365.        flag.timeout = true;
  366.       goto ForceTheMove2;
  367.      }
  368.     if ((TCflag)||(backsrchaborted))
  369.      {
  370.       goto ForceTheMove2; // for now use 2, it was ForceTheMove before
  371.      }
  372.     else
  373.      {
  374.       goto ForceTheMove2;
  375.      }
  376.    }
  377. #endif
  378.   ExtraTime = 0;
  379.   ExaminePosition ();
  380. //  score = ScorePosition (side);
  381.   stage= -1; /* Force init in UpdateWeights() */
  382.   start_score= Tscore[0]= Tscore[1]= score=
  383.     evaluate (side, 1, 1, 0, -9999, 9999, 0, &InChkDummy);
  384.   start_stage= stage;
  385. #ifdef QUIETBACKGROUND
  386.   if (!background)
  387. #endif /* QUIETBACKGROUND */
  388.     ShowSidetoMove ();
  389. #ifdef notdef
  390.   if (TCflag && TCcount < MAXTCCOUNT)
  391.     if (score < SCORETIME)
  392.       {
  393.     ExtraTime += TCleft;
  394.     TCcount++;
  395.       }
  396. #endif
  397.  
  398. #ifdef QUIETBACKGROUND
  399.   if (!background)
  400. #endif /* QUIETBACKGROUND */
  401.     SearchStartStuff (side);
  402. #ifdef HISTORY
  403. #if defined(NOMEMSET) || defined(MSDOS)
  404.   for (i = 0; i < 32768; i++)
  405.     history[i] = 0;
  406. #else
  407. #ifndef AMIGA
  408.   memset ((unsigned char *) history, 0, (unsigned long)sizeof (history));
  409. #else
  410.   ClearMem(history,sizeof (history));
  411. #endif
  412. #endif /* NOMEMSET */
  413. #endif
  414.   FROMsquare = TOsquare = -1;
  415.   PV = 0;
  416.   if (iop == 1)
  417.     hint = 0;
  418. #ifndef AMIGA
  419.   for (i = 0; i < MAXDEPTH; i++)
  420.    {
  421.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  422.    }
  423. #else
  424.   ClearMem(PrVar,MAXDEPTH*sizeof(PrVar[0]));
  425.   ClearMem(killr0,MAXDEPTH*sizeof(killr0[0]));
  426.   ClearMem(killr1,MAXDEPTH*sizeof(killr1[0]));
  427.   ClearMem(killr2,MAXDEPTH*sizeof(killr2[0]));
  428.   ClearMem(killr3,MAXDEPTH*sizeof(killr3[0]));
  429. #endif
  430.   /* set initial window for search */
  431.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  432.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  433.   rpt = 0;
  434.   TrPnt[1] = 0;
  435.   root = &Tree[0];
  436.   MoveList (side, 1);
  437. if(TrPnt[2]-TrPnt[1] == 0){
  438.     /* if no moves and not in check then draw */
  439.   if (!(SqAtakd3 (PieceList[side][0], xside)))
  440.     {
  441.       root->flags |= draw;
  442.       DRAW = CP[87];            /* No moves */
  443.     } else {
  444. #if !defined CLIENT
  445.     flag.quit = 
  446. #endif
  447.     flag.mate = true;
  448.     root->score = -9999;
  449.     }
  450.     if(iop !=2){
  451.     OutputMove(mystr);
  452.     }
  453.     return;
  454.     }
  455.   for (i = TrPnt[1]; i < TrPnt[2]; i++) pick (i, TrPnt[2] - 1);
  456.   /* can I get a book move? */
  457.   if ((flag.regularstart && Book))
  458.     {
  459.       flag.timeout = bookflag = OpeningBook (&hint, side);
  460.       if (TCflag)
  461.        {
  462.     ResponseTime += ResponseTime;
  463.         OrigResponse = ResponseTime;
  464.        }
  465.     }
  466. #ifdef SPEED_PRECALC
  467.   if ((!flag.timeout)&&(ThinkAheadWorked))
  468.    {
  469.     flag.timeout = DoPreCalc(&hint,side);
  470.    }
  471. #endif
  472.   /* zero stats for hash table */
  473. #ifdef ZEROALLBETWEENPLY
  474.   if (!bookflag)
  475.    {
  476.     ZeroTTable();
  477.     EADD = EGET = 0;
  478.    }
  479. #endif
  480.   reminus = replus = 0;
  481.   GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  482.   globalscore = plyscore = score;
  483.   zwndw = 20;
  484.   Jscore = trying_again = global_tmp_score = previous_score = 0;
  485. #include "debug4.h"
  486.   /********************* main loop ********************************/
  487.     Sdepth = (MaxSearchDepth<(MINDEPTH-1))?MaxSearchDepth:(MINDEPTH-1);
  488. /*printf("\n\n");*/
  489. ForceTheMove:
  490.   while (!flag.timeout)
  491.     {
  492. /*printf("time0 = %d et = %d SDepth = %d GameCnt = %d\n",time0, et,Sdepth,GameCnt);*/
  493. /*printf("ThinkAheadWorked = %d  ThinkAheadDepth = %d\n",ThinkAheadWorked,ThinkAheadDepth);*/
  494.       /* go down a level at a time */
  495.       Sdepth++;
  496. #if defined NULLMOVE || defined DEEPNULL
  497.       null = 0;
  498.       PVari = 1;
  499. #endif
  500. //      DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
  501.       DepthBeyond = Sdepth +
  502.         ((Sdepth == 1) ? FBEYOND : flag.threat ? SBEYOND: TBEYOND);
  503.       no_null= (emtl[xside] == 0 || emtl[side] == 0);
  504.  
  505. #if !defined CHESSTOOL && !defined XBOARD
  506. #ifdef QUIETBACKGROUND
  507.       if (!background)
  508. #endif /* QUIETBACKGROUND */
  509.     ShowDepth (' ');
  510. #endif
  511.       root->score= Tscore[0]= Tscore[1]= start_score;
  512.       /* search at this level returns score of PV */
  513. //      score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt, QBLOCK);
  514.       score = search (side, 1, Sdepth, 0, alpha, beta, PrVar, &rpt, QBLOCK, false);
  515.       /* save PV as killer */
  516.       for (i = 1; i <= Sdepth; i++)
  517.     killr0[i] = PrVar[i];
  518.  
  519.       /* low search failure re-search with (-inf,score) limits  */
  520.       if (score < alpha)
  521.     {
  522. #if !defined CHESSTOOL && !defined XBOARD
  523.       reminus++;
  524. #ifdef QUIETBACKGROUND
  525.       if (!background)
  526. #endif /* QUIETBACKGROUND */
  527.         ShowDepth ('-');
  528. #endif
  529.       if (TCflag && TCcount < MAXTCCOUNTR)
  530.         {
  531.           TCcount = MAXTCCOUNTR - 1;
  532.           ExtraTime += (8 * TCleft);
  533.         }
  534. //      score = search (side, 1, Sdepth, -9999, 9999, PrVar, &rpt, QBLOCK); // was -99999, 9999
  535.           root->score= Tscore[0]= Tscore[1]= start_score;
  536.       score = search (side, 1, Sdepth, 0, -9999, 9999, PrVar, &rpt,QBLOCK,false);
  537.     }
  538.       /* high search failure re-search with (score, +inf) limits */
  539.       if (score > beta && !(root->flags & exact))
  540.     {
  541. #if !defined CHESSTOOL && !defined XBOARD
  542.       replus++;
  543. #ifdef QUIETBACKGROUND
  544.       if (!background)
  545. #endif /* QUIETBACKGROUND */
  546.         ShowDepth ('+');
  547. #endif
  548.           root->score= Tscore[0]= Tscore[1]= start_score;
  549.       score = search (side, 1, Sdepth, 0, -9999, 9999, PrVar, &rpt,QBLOCK,false);
  550.     }
  551.       /**************** out of search ********************************************/
  552. ForceTheMove2:
  553.       if ((flag.timeout)||(flag.musttimeout)||(flag.back))
  554.        earlyflag = true;
  555.       else
  556.        earlyflag = false;
  557.       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
  558.        {
  559.     flag.timeout = true;
  560.        }
  561.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
  562.     {
  563.       if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
  564.         {
  565.           TCcount++;
  566.           ExtraTime += TCleft;
  567.         }
  568.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  569.         {
  570.           TCcount++;
  571.           ExtraTime += TCleft;
  572.         }
  573.     }
  574.       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250)) ExtraTime = 0;
  575. /*printf("sdepth = %d mindepth = %d TCflag = %d \n4*et = %d respt = %d extra = %d\n",Sdepth,MINDEPTH,TCflag,4*et,ResponseTime,ExtraTime);*/
  576.       if (root->flags & exact) flag.timeout = true;
  577.       /*else if (Tree[1].score < -9000) flag.timeout = true;*/
  578.       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2*ResponseTime + ExtraTime))) flag.timeout = true;
  579.       /************************ time control ***********************************/
  580.  
  581.       /* save PV as killer */
  582.       for (i = 1; i <= Sdepth + 1; i++) killr0[i] = PrVar[i];
  583.       if (!flag.timeout) start_score = Tscore[0] = score;
  584.       /* if (!flag.timeout) */
  585. //      for (i = TrPnt[1]+1; i < TrPnt[2]; i++) if (!pick (i, TrPnt[2] - 1)) break;
  586.       /* if done or nothing good to look at quit */
  587.       if ((root->flags & exact) || (score < -9000)) flag.timeout = true;
  588.       /* find the next best move put below root */
  589. #include "debug13.h"
  590.       if (!flag.timeout)
  591.     {
  592.       /* */
  593. #if !defined NODYNALPHA
  594.       Jscore = (plyscore + score) >> 1;
  595. #endif
  596.       zwndw = 20 + abs (Jscore / 12);
  597.       plyscore = score;
  598.       /* recompute search window */
  599.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  600. #if !defined NODYNALPHA
  601.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - zwndw;
  602. #else
  603.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  604. #endif
  605.     }
  606. #if !defined CHESSTOOL && !defined XBOARD
  607. #ifdef QUIETBACKGROUND
  608.       if (!background)
  609. #endif /* QUIETBACKGROUND */
  610.     ShowResults (score, PrVar, '.');
  611. #ifdef DEBUG41
  612.       debug41 (score, PrVar, '.');
  613. #endif
  614. #endif
  615. #include "debug16.h"
  616. #ifdef CHECKMOVERESULTS
  617.       if ((score >= 11000)&&(!got_20000))
  618.        {
  619.         got_20000 = 1;
  620.         Sdepth = 0;
  621.         goto start_again;
  622.        }
  623.       if (((flag.timeout)&&((!PrVar[1])||(!PrVar[2]))&&(!(root->flags & exact))&&(iop != 2)&&(abs(score) < 9000)&&(abs(score)>25))) /* do not trust this move! */
  624.        {
  625.         if ((Sdepth > 2))
  626.          {
  627.           if ((earlyflag))
  628.            {
  629.             Sdepth--;
  630.            }
  631.           if (!trying_again)
  632.            { /* this is first bogus move we have seen */
  633.             ResponseTime = ResponseTime << 1;
  634.             ExtraTime += 251;
  635.            }
  636.           else
  637.            { /* this is not 1st bogus move we have seen */
  638.             ExtraTime += 201;
  639.            }
  640.           trying_again = 1;
  641.           flag.timeout = false;
  642.           flag.back = false;
  643.           flag.musttimeout = false;
  644.          }
  645.        }
  646.       else if (trying_again) /* this move is trustworthy, to an extent */
  647.        {
  648.         if ((TCflag && ((4 * et) > (ResponseTime + ExtraTime - 251)))||(root->flags & exact)) 
  649.          flag.timeout = true;
  650.        }
  651. #endif
  652.       previous_score = score;
  653.     } /* while !flag.timeout */
  654.   /******************************* end of main loop ***********************************/
  655.   /* background mode */
  656.   if (iop == 2)
  657.    {
  658.     if (bookflag) Sdepth = 0;
  659.     if (!flag.easy)
  660.      {
  661.       Sdepth2 = Sdepth;
  662.       if (Sdepth2 > (GlobalTgtDepth+1))
  663.        Sdepth2--;
  664. #ifdef SPEED_PRECALC
  665.       PreCalcedMove = (Tree[TrPnt[1]].f << 8) | (Tree[TrPnt[1]].t);
  666.       PreCalcedHint = ((PrVar[1]) ? PrVar[2] : 0);
  667. #endif
  668.      }
  669.     return;
  670.    }
  671. #include "debug4.h"
  672.   if (rpt >= 2)
  673.     {
  674.       root->flags |= draw;
  675.       DRAW = CP[101];        /* Repetition */
  676.     }
  677.   else
  678.     /* if no moves and not in check then draw */
  679.   if ((score == -9999) && !(SqAtakd3 (PieceList[side][0], xside)))
  680.     {
  681.       root->flags |= draw;
  682.       DRAW = CP[87];        /* No moves */
  683.     }
  684.   else if (GameCnt == MAXMOVES)
  685.     {
  686.       root->flags |= draw;
  687.       DRAW = CP[80];        /* Max Moves */
  688.     }
  689.   /* not in book so set hint to guessed move for other side */
  690.   if (!bookflag)
  691.     hint = ((PrVar[1]) ? PrVar[2] : 0);
  692.  
  693.   /* if not mate or draw make move and output it */
  694.   if (((score > -9999) && (rpt <= 2)) || (root->flags & draw))
  695.     {
  696.       MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore);
  697. #if !defined NOMATERIAL
  698.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  699.     {
  700.       root->flags |= draw;
  701.       DRAW = CP[224];    /* No pieces */
  702.     }
  703.       else
  704. #endif
  705.       if (!PieceCnt[black] && !PieceCnt[white])
  706.     {
  707.       root->flags |= draw;
  708.       DRAW = CP[88];    /* No pieces */
  709.     }
  710.       algbr (root->f, root->t, (short) root->flags);
  711.     }
  712.   else
  713.     {
  714.       algbr (0, 0, 0);        /* Zero move string when mate. */
  715.       root->score = score;    /* When mate, ignore distinctions!
  716.                  * --SMC */
  717.     }
  718.   g = &GameList[GameCnt];
  719.   if (g->flags & capture && g->piece == king)
  720.     {
  721.       flag.mate = flag.illegal = true;
  722.     }
  723.   /* If Time Control get the elapsed time */
  724.   if (TCflag)
  725.     ElapsedTime (1);
  726.   /* if mate set flag */
  727.   if ((score == -9999 || score == 9999))
  728.     flag.mate = true;
  729.   OutputMove (mystr);
  730.   /* if mate clear hint */
  731.   if (flag.mate)
  732.     hint = 0;
  733.   /* if pawn move or capture or castle or promote zero repitition array */
  734.   if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask | promote)))
  735.     {
  736.       Game50 = GameCnt;
  737.       ZeroRPT ();
  738.     }
  739.   /* add move to game list */
  740.   g->score = score;
  741.   g->nodes = NodeCnt;
  742.   g->time = (et +50)/100;
  743.   g->depth = Sdepth;
  744. #include "debug40.h"
  745.   /* update time comtrol info */
  746.   if (TCflag)
  747.     {
  748. #if defined CHESSTOOL || defined XBOARD
  749.       TimeControl.clock[side] -= (et + OperatorTime + 45);
  750.       timecomp[compptr] = (et + OperatorTime + 45);
  751. #else
  752.       TimeControl.clock[side] -= (et + OperatorTime);
  753.       timecomp[compptr] = (et + OperatorTime);
  754. #endif
  755.       /* finished our required moves - setup the next set */
  756.       --TimeControl.moves[side];
  757.     }
  758.   /* check for end conditions */
  759.   if ((root->flags & draw) /* && flag.bothsides */ )
  760. #if !defined CLIENT
  761.      flag.mate = true;
  762. #else 
  763.     ;
  764. #endif
  765.   else if (GameCnt == MAXMOVES)
  766.     {
  767.       flag.mate = true;
  768.     }
  769.   /* out of move store, you loose */
  770.   else
  771.     /* switch to other side */
  772.     player = xside;
  773.   Sdepth = 0;
  774. }
  775.  
  776. int
  777. search (short int side,
  778.     register short int ply,
  779.     register short int depth,
  780.     short ext,
  781.     short int alpha,
  782.     short int beta,
  783.     short unsigned int *bstline,
  784.     short int *rpt,
  785.         short SAVEHT,
  786.     int didnull)
  787.  
  788. /*
  789.  * Perform an alpha-beta search to determine the score for the current board
  790.  * position. If depth <= 0 only capturing moves, pawn promotions and
  791.  * responses to check are generated and searched, otherwise all moves are
  792.  * processed. The search depth is modified for check evasions, certain
  793.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  794.  * the nominal search depth.
  795.  */
  796.  
  797.  
  798. {
  799.   register short j, pnt;
  800.   short tempb, tempc, tempsf, tempst;
  801.   short xside, pbst, score, rcnt, InChk;
  802.   unsigned short mv, nxtline[MAXDEPTH];
  803.   struct leaf *node, tmp;
  804.   short best = -12000;
  805. #ifdef DOIT_4PL68WAY // this is the 4pl68 way to extend search
  806.   int __aligned max_time;
  807. #endif
  808.   short bestwidth = 0;
  809. #if defined NULLMOVE || defined DEEPNULL
  810.   short int __aligned PVsave;
  811.   short int __aligned PVarisave;
  812.   unsigned short __aligned verydeep=0xffff;
  813. #endif
  814. #ifdef DEBUG
  815.   int xxxtmp;
  816.   int tracetmp;
  817. #endif
  818.   short __aligned extdb= 0;
  819.   short __aligned threat= 0;      /* tom@izf.tno.nl */
  820.   short __aligned threat2= 0;     /* tom@izf.tno.nl */
  821.   short __aligned do_pvs;
  822.  
  823.   NodeCnt++;
  824.   /* look every ZNODE nodes for a timeout */
  825.   if (!null)
  826.    {
  827.   if (NodeCnt > ETnodes )
  828.     {
  829.       ElapsedTime (2);
  830.       if (flag.back)
  831.     {
  832.       flag.back = false;
  833.       flag.timeout = true;
  834.       flag.musttimeout = false;
  835.     }
  836.       else if (TCflag || MaxResponseTime)
  837.     {
  838.       if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH && abs(best) < 10000)
  839.         {            /* try to extend to finish ply */
  840. #define TRYEXTEND 1
  841. #ifdef TRYEXTEND
  842.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(GameCnt > 10))
  843.         {
  844.           flag.musttimeout = true;
  845.           TCcount += 1;
  846.           ExtraTime += TCleft;
  847.         }
  848.           else
  849.         {
  850.           flag.timeout = true;
  851.           flag.musttimeout = false;
  852.         }
  853. #else
  854.           if ((TCflag && TCcount < MAXTCCOUNTX)&&(flag.easy))
  855.         {
  856.           flag.musttimeout = true;
  857.           TCcount += 1;
  858.           ExtraTime += TCleft;
  859.         }
  860.           else
  861.         {
  862.           flag.timeout = true;
  863.           flag.musttimeout = false;
  864.         }
  865. #endif
  866.         }
  867.     }
  868.     }
  869.   else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
  870.     {
  871.       flag.timeout = true;
  872.       flag.musttimeout = false;
  873.     }
  874.    } // !null
  875.   xside = side ^ 1;
  876.   if (ply == 1) INCscore = 0; // TMP!! MY Fix for INCscore not init at ply 1
  877.   /* slk is lone king indicator for either side */
  878.   score = evaluate (side, ply, depth, ext, alpha, beta, INCscore, &InChk);
  879.  
  880.   /*
  881.    * check for possible repitition if so call repitition - rpt is
  882.    * repeat count
  883.    */
  884.   if (rpthash[side][hashkey & 0xFF] > 0)
  885.     {
  886.       *rpt = repetition ();
  887.       if (*rpt == 1)
  888.         score = 0;
  889.       else if (*rpt == 2)
  890.         {
  891.           bstline[ply] = 0;
  892.           return (0);
  893.         }
  894.     }
  895.   else
  896.     *rpt = 0;
  897.  
  898.   /* score > 9000 its a draw or mate */
  899.   if (score > 9000 /*|| root->flags & draw*/)
  900.     {
  901.       bstline[ply] = 0;
  902.       return (score);
  903.     }
  904.   /* Do we need to add depth because of special conditions */
  905.   /* if in check or pawn threat or in capture sequence search deeper */
  906.   /*************************************** depth extensions ***********************************/
  907. #ifdef OLDEXT
  908.   if (depth > 0)
  909.     {
  910.       /* Allow opponent a chance to check again */
  911.       if (InChk)
  912.     depth = (depth < 2) ? 2 : depth;
  913.       else if (PawnThreat[ply - 1] ||
  914.            (flag.rcptr && (score > alpha) &&
  915.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  916.     ++depth;
  917.     }
  918.   else
  919.     {
  920.       if (score >= alpha &&
  921.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 /* && ply == Sdepth + 1*/)))
  922.     depth = 1;
  923.       else if (score <= beta &&
  924.            ((ply < Sdepth + 4) && (ply > 4) &&
  925.  
  926.         ChkFlag[ply - 2] && ChkFlag[ply - 4]))
  927.     {
  928.               depth = 1;
  929.         }
  930.     }
  931. #else
  932.  
  933. #define DOTHREAT    (start_stage < THRSTAGE)
  934. #define DOCHECK     (start_stage < CHECKSTAGE)
  935.  
  936.   Threat[ply]= 0;
  937.   if (depth > 0)
  938.     {
  939.       /* Allow opponent a chance to check again */
  940.       if (InChk) {
  941. #ifdef DOIT_4PL68WAY // this is the 4pl68 way to extend search
  942.           if (TCflag)
  943.            max_time = ((OrigResponse<<2) + ExtraTime);
  944.           else
  945.            max_time = 99999999;
  946.           if (et >= max_time)
  947.            {
  948.             if (flag.threat)
  949.               depth= DOCHECK && (ply+depth<DepthBeyond-DEPTHMARGIN) ?
  950.                 depth+1: depth;
  951.             else
  952.               depth= (depth < 2) ? 2 : depth;
  953.            }
  954.           else
  955.            depth++;
  956. #else // this is the Kong Sian way, always extend check search
  957.       // this way costs more time but may be better
  958.           depth++;
  959. #endif
  960.       }
  961.       else if ((ply>1 && PawnThreat[ply - 1] && ply+depth<DepthBeyond-DEPTHMARGIN) ||
  962.                (flag.rcptr && ply>2 && CptrFlag[ply - 1] && CptrFlag[ply - 2] &&
  963.                ((ply<Sdepth+2 && CptrFlag[ply-1]==CptrFlag[ply-2]) ||
  964. // the next line is a fix from Kong Sian, old way may be better
  965.             (score > root->score - valueP/4 && score < root->score + valueP/4))) // FIX by Kong SIAN
  966. //               (score > alpha && score < beta))) // OLD 4PL68 way
  967.                )
  968.           ++depth;
  969.     }
  970.   else
  971.     { 
  972.       int tripple_check = 0;
  973.       if (score >= alpha &&
  974.           (InChk || (ply>1 && PawnThreat[ply - 1] && depth<DepthBeyond-4)
  975.           || (hung[side] > 1 /*&& !ext*/))) { // fix from Kong Sian
  976.         threat2= 1;
  977.         ext++;
  978.         depth= 1;
  979.       }
  980.       else if (score <= beta &&
  981.                ((ply<Sdepth+4 && ply>4 &&
  982.                 ChkFlag[ply-2] && ChkFlag[ply-4] &&
  983.                 (ChkFlag[ply-2] != ChkFlag[ply-4] ||
  984.                 (flag.threat && DOTHREAT && QueenCheck[ply-2])))
  985.           ||
  986.                 (flag.threat && ply<DepthBeyond-DEPTHMARGIN && ply>6
  987.                 && ChkFlag[ply-2] && ChkFlag[ply-4] && ChkFlag[ply-6]
  988.                 &&  (tripple_check=1)
  989.                 && ((ply < Sdepth+4 ?
  990.                   (ChkFlag[ply-2] != ChkFlag[ply-4] || ChkFlag[ply-2] !=
  991. ChkFlag [ply-6])
  992.                   : (ChkFlag[ply-2] != ChkFlag[ply-4] &&
  993.                      ChkFlag[ply-2] != ChkFlag[ply-6] &&
  994.                      ChkFlag[ply-4] != ChkFlag[ply-6]))
  995.                 || (DOTHREAT && QueenCheck[ply-2]
  996.                 && QueenCheck[ply-4] && QueenCheck[ply-6]
  997.                 && QueenCheck[ply-2] != QueenCheck[ply-6]))
  998.                 ))) {
  999.           if (tripple_check && DepthBeyond < Sdepth+13+DEPTHMARGIN)
  1000.             {
  1001.               extdb += 2;
  1002.               DepthBeyond += 2;
  1003.             }
  1004.           depth= 1;
  1005.           ext++;
  1006.           Threat[ply]= threat= 1;
  1007.         }
  1008.     }    
  1009.   ThreatSave[ply]= ((ply>1 && ThreatSave[ply-1]) || threat);
  1010. #endif
  1011.   /*******************************************************************************************/
  1012.   /* try the local transition table if it's there */
  1013. #if ttblsz
  1014.   if (/*depth > 0 &&*/ flag.hash && ply > 1)
  1015.     {
  1016.       if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  1017.     {
  1018.       bstline[ply] = PV;
  1019.       bstline[ply + 1] = 0;
  1020. #include "debug64.h"
  1021.       if (beta == -20000)
  1022.         return (score);
  1023.       if (alpha > beta)
  1024.         return (alpha);
  1025.     }
  1026. #ifdef HASHFILE
  1027.       /* ok try the transition file if its there */
  1028.       else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  1029.      && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  1030.     {
  1031. #ifdef notdef
  1032.       int hgood = false;
  1033.       int f = PV >> 8;
  1034.       int t = PV & 0x3f;
  1035.       register int i;
  1036.  
  1037.       /*
  1038.        * if you find something put it in the local table
  1039.        * for future reference
  1040.        */
  1041.       hgood = false;
  1042.       for (i = TrPnt[ply]; i < TrPnt[ply + 1]; i++)
  1043.         {
  1044.           if (Tree[i].f == f && Tree[i].t == t)
  1045.         {
  1046.           hgood = true;
  1047.           break;
  1048.         }
  1049.         }
  1050.       if (hgood)
  1051.         {
  1052. #endif
  1053.           PutInTTable (side, score, depth, ply, alpha, beta, PV);
  1054.           bstline[ply] = PV;
  1055.           bstline[ply + 1] = 0;
  1056.           if (beta == -20000)
  1057.         return (score);
  1058.           if (alpha > beta)
  1059.         return (alpha);
  1060. #ifdef notdef
  1061.         }
  1062. #endif
  1063. #include "debug10.h"
  1064.     }
  1065. #endif /* HASHFILE */
  1066.     }
  1067. #endif /* ttblsz */
  1068.  
  1069.   if (ply>1) TrPnt[ply+1]= TrPnt[ply]; // TMP!! My Fix for move gen
  1070.  
  1071.   /*
  1072.    * if more then DepthBeyond ply past goal depth or at goal depth and
  1073.    * score > beta quit - means we are out of the window
  1074.    */
  1075.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  1076.     {
  1077.       return (score);
  1078.     }
  1079.  
  1080.   /*
  1081.    * if below first ply and not at goal depth generate all moves else
  1082.    * only capture moves
  1083.    */
  1084.   if (ply > 1)
  1085.     if (depth > 0  /*|| ply<(SDEPTHLIM)*/||  // ply < sdlim was in 4pl66
  1086.     (background && ply<Sdepth + 2))
  1087.       {
  1088.     MoveList (side, ply);
  1089. // next line is NEW from 4pl67
  1090.       if (TrPnt[ply] == TrPnt[ply + 1]) { if(!InChk) return ((side==computer)?contempt:-contempt); else return (-10001+ply); }
  1091.       }
  1092.     else{
  1093.       CaptureList (side, ply);
  1094.       SAVEHT = false;
  1095.     }
  1096.  
  1097.   /* no moves return what we have */
  1098.  
  1099.   /*
  1100.    * normally a search will continue til past goal and no more capture
  1101.    * moves exist
  1102.    */
  1103.   /* unless it hits DepthBeyond */
  1104.   if (TrPnt[ply] == TrPnt[ply + 1])
  1105.     {
  1106.       return (score);
  1107.     }
  1108.  
  1109.  
  1110.  
  1111.   /* if not at goal set best = -inf else current score */
  1112.      best = (depth >0) ? -12000:score;
  1113. #ifdef NULLMOVE
  1114.  
  1115.   PVarisave = PVari;
  1116.   if (!null &&                         /* no previous null-move */
  1117.       !PVari &&                        /* no null-move during the PV */
  1118.       (ply > 1) && // was 2 changed by Kong Sian
  1119.       (ply <= Sdepth) &&                       /* not at ply 1 */
  1120.       (depth > 2) && // changed by Kong Sian   /* not during the quienscesearch */
  1121.       !InChk &&                        /* no check */
  1122.       ((mtl[side] + mtl[xside]) > NULLMOVELIM))
  1123.     /* enough material such that zugzwang is unlike but who knows which value
  1124.        is suitable? */
  1125.     {
  1126.       
  1127.       /* ok, we make a null move, i.e.  this means we have nothing to do
  1128.       but we have to keep the some arrays up to date otherwise gnuchess
  1129.       gets confused.  Maybe somebody knows exactly which informations are
  1130.      important and which not.
  1131.  
  1132.      Another idea is that we try the null-move first and generate the
  1133.      moves later.  This may save time but we have to take care that
  1134.      PV and other variables contain the right value so that the move
  1135.      ordering works right.
  1136.      */
  1137.       register struct GameRec *g;
  1138.       
  1139.       nxtline[ply + 1] = 0;
  1140.       CptrFlag[ply] = 0;
  1141.       PawnThreat[ply] = 0;
  1142.       Tscore[ply] = score;
  1143.       PVsave = PV;
  1144.       PV = 0;
  1145.       null = 1;
  1146.       g = &GameList[++GameCnt];
  1147.       g->hashkey = hashkey;
  1148.       g->hashbd = hashbd;
  1149.       epsquare = -1;
  1150.       TOsquare = -1;
  1151.       g->Game50 = Game50;
  1152. #ifdef LONGINTS
  1153.       g->gmove = 0xffffffff;
  1154. #else
  1155.       g->gmove = 0xffff;
  1156. #endif
  1157.       g->flags = 0;
  1158.       g->piece = 0;
  1159.       g->color = neutral;
  1160.       
  1161. //      best = -search (xside, ply + 1, false, depth - 2, -beta - 1, -beta, nxtline, &rcnt,false,false);
  1162. //this next line a fix from Kong Sian replaces above line
  1163.       best = -search (xside, ply + 1, false, depth - 2, -beta, -beta, nxtline, &rcnt,false,false);
  1164.       null = 0;
  1165.       PV = PVsave;
  1166.       GameCnt--;
  1167.       if (best < alpha) best = -12000;
  1168.       else if (best > 0 && best > beta) return (best);
  1169.       else
  1170.      best = -12000;
  1171.     }
  1172. #else 
  1173. #ifdef DEEPNULL
  1174.  
  1175.   /*
  1176.    * The deepnull algoritm is taken from the article by
  1177.    * Christian Donninger in ICCA journal Vol 16, No. 3.  TomV
  1178.    */
  1179.   PVarisave = PVari;
  1180.   if ((myflagdeepnull ? !didnull : !null) &&    /* no previous null-move */
  1181.     //  !flag.nonull &&
  1182.       !no_null &&
  1183.       !PVari &&            /* no null-move during the PV */
  1184.       (ply > (myflagdeepnull ? 1: 2)) &&        /* not at ply 1 */
  1185.       (score > alpha - 150 || !myflagdeepnull) &&
  1186.       (ply <= Sdepth || myflagdeepnull) &&
  1187.       (depth > (myflagdeepnull ? (verydeep ? 1: 2): 3)) &&
  1188.       !InChk &&            /* no check */
  1189.       /* enough material such that zugzwang is unlikely: */
  1190.       ! (emtl[xside] == 0 || emtl[side] <= valueB))
  1191.     {
  1192.  
  1193.       /* ok, we make a null move, i.e.  this means we have nothing to do
  1194.       but we have to keep the some arrays up to date otherwise gnuchess
  1195.       gets confused.
  1196.  
  1197.      Another idea is that we try the null-move first and generate the
  1198.      moves later.  This may save time but we have to take care that
  1199.      PV and other variables contain the right value so that the move
  1200.      ordering works right.
  1201.      */
  1202.       CptrFlag[ply] = 0;
  1203.       PawnThreat[ply] = 0;
  1204.       Tscore[ply] = score;
  1205.       PVsave = PV;
  1206.       PV = 0;
  1207.       epsquare = -1;
  1208.       TOsquare = -1;
  1209.       if (!null)
  1210.         null= ply;
  1211.       if (myflagdeepnull) {
  1212.         int nmscore = -search (xside, ply + 1, (depth >= 3 ? depth - 3: 0), ext, -beta, -alpha, nxtline, &rcnt,false,1);
  1213.         if (ply == null)
  1214.           null = 0;
  1215.         PV = PVsave;
  1216.     if (nmscore > beta) {
  1217.       DepthBeyond-= extdb;
  1218.       return nmscore;
  1219.         }
  1220.     if (nmscore > alpha)
  1221.       best= nmscore;
  1222.         if (depth <= 3 && ply < DepthBeyond-depth-4
  1223.             && score >= beta && nmscore < score - 350)
  1224.               depth++;
  1225.       } else {
  1226. // change to -beta,-beta from K SIAN
  1227.         best = -search (xside, ply + 1, depth - 2, ext, -beta - 1, -beta, nxtline, &rcnt, false, 1);
  1228. //        best = -search (xside, ply + 1, depth - 2, ext, -beta, -beta, nxtline, &rcnt, false, 1);
  1229.         null = 0;
  1230.         PV = PVsave;
  1231.         if (best < alpha) best = -12000;
  1232.         else if (best > beta) {
  1233.        DepthBeyond-= extdb;
  1234.            return (best);
  1235.         }  else best = -12000;
  1236.       }
  1237.     }
  1238. #endif //deepnull
  1239. #endif // nullmove
  1240.   /* if best so far is better than alpha set alpha to best */
  1241.     if(best>alpha)alpha=best;
  1242.   /********************** main loop ************************************************************************/
  1243.   /* look at each move until no more or beta cutoff */
  1244.    do_pvs = 0;
  1245. //   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] &&
  1246. //    (best <= beta || (ply == 1 && best > 9000)); pnt++) /* Find best mate, TomV TMP!!*/
  1247.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  1248.     {
  1249.       /* find the most interesting looking of the remaining moves */
  1250.       if (ply > 1)
  1251.     pick (pnt, TrPnt[ply + 1] - 1);
  1252. #if defined NULLMOVE || defined DEEPNULL
  1253.       PVari = PVarisave && (pnt == pbst/*TrPnt[ply]*/);  /* Is this the PV? */
  1254. #endif
  1255.  
  1256.       node = &Tree[pnt];
  1257.       /* is this a forbidden move */
  1258.       if (pnt == pbst)
  1259.        do_pvs = myflagpvs && PVari; // this line a fix from Kong Sian, replaced line below
  1260. //        do_pvs= myflagpvs && !null && (PrVar[ply] == ((node->f << 8) | node->t));
  1261.       if (ply == 1 && node->score == -32768)
  1262.     continue;
  1263. #ifdef DEBUG
  1264.     if(debuglevel & (512 | 1024)){
  1265.         if(!tracen)traceflag = ((ply >traceply)?false:true);
  1266.          else
  1267.         if(ply <= tracen && (ply ==1 || traceflag))
  1268.             { 
  1269.             if(trace[ply] == (Tree[pnt].t |(Tree[pnt].f<<8))) traceflag = true; else traceflag = false; }
  1270.         tracelog[ply] = (Tree[pnt].t |(Tree[pnt].f<<8));
  1271.         tracelog[ply+1] = 0;
  1272. }
  1273. #endif
  1274.       nxtline[ply + 1] = 0;
  1275.  
  1276. #if !defined CHESSTOOL && !defined XBOARD
  1277.       /* if at top level */
  1278.       if (ply == 1)
  1279.     {            /* at the top update search status */
  1280.       if (flag.post)
  1281. #ifdef QUIETBACKGROUND
  1282.         if (!background)
  1283. #endif /* QUIETBACKGROUND */
  1284.           ShowCurrentMove (pnt, node->f, node->t);
  1285.     }
  1286. #endif
  1287.       /* make the move and go deeper */
  1288.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1289. // FIX from Kong Sian for cpt flag
  1290. //      CptrFlag[ply] = (node->flags & capture); // OLD way
  1291.       CptrFlag[ply] = (node->flags & capture ? TOsquare+1 : 0); // K. Sian way
  1292.       PawnThreat[ply] = (node->flags & pwnthrt);
  1293.       Tscore[ply] = node->score;
  1294.       PV = node->reply;
  1295. #ifdef DEBUG
  1296.       xxxtmp = node->score;
  1297.       tracetmp = traceflag;
  1298. #endif
  1299.       if (do_pvs) {
  1300.             if (pbst == pnt) {
  1301.               node->score= -search (xside, ply + 1,
  1302.                                  depth > 0 ? depth - 1 : 0, ext,
  1303.                                  -beta, -alpha,
  1304.                                  nxtline, &rcnt,SAVEHT, 0);
  1305.             } else {
  1306.               node->score= -search(xside, ply + 1,
  1307.                               depth > 0 ? depth - 1 : 0, ext,
  1308.                               -alpha-1, -alpha,
  1309. // below line is a fix from Kong Sian, replaces above line
  1310. //                              -alpha, -alpha,
  1311.                               nxtline, &rcnt,SAVEHT, 0);
  1312. // next if stmt improved by Kong Sian after 4pl68
  1313.               if (/*node->score >= best && */alpha <= node->score
  1314.               /*&& node->score <= beta*/)
  1315.                   node->score = -search (xside, ply + 1,
  1316.                                  depth > 0 ? depth - 1 : 0, ext,
  1317.                                  -beta, /*-node->score*/-alpha,
  1318.                                  nxtline, &rcnt,SAVEHT, 0);
  1319.             }
  1320.           } else
  1321.  
  1322.       node->score = -search (xside, ply + 1,
  1323.                  (depth > 0) ? depth - 1 : 0, ext,
  1324.                  -beta, -alpha,
  1325.                  nxtline, &rcnt, SAVEHT, false);
  1326.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  1327.       if (abs (node->score) > 9000) node->flags |= exact;
  1328.           else if (rcnt == 1) node->score = 0;
  1329.       if(node->score == (9999-ply) && !ChkFlag[ply] ) {node->flags |= draw;
  1330.           node->score = ((side == computer) ? contempt : -contempt);}
  1331. #include "debug256.h"
  1332.       if ((rcnt >= 2 || GameCnt - Game50 > 99 
  1333. /*|| (node->score == 9999 - ply && !ChkFlag[ply])*/
  1334.           ))
  1335.         {
  1336.           node->flags |= (draw | exact);
  1337.           DRAW = CP[58];    /* Draw */
  1338.           node->score = ((side == computer) ? contempt : -contempt);
  1339.         }
  1340.       node->reply = nxtline[ply + 1];
  1341.       /* reset to try next move */
  1342.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1343.       /* if best move so far */
  1344.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  1345.     {
  1346.       /*
  1347.        * all things being equal pick the denser part of the
  1348.        * tree
  1349.        */
  1350.       bestwidth = node->width;
  1351.  
  1352.       /*
  1353.        * if not at goal depth and better than alpha and not
  1354.        * an exact score increment by depth
  1355.        */
  1356.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  1357.         node->score += depth;
  1358.       best = node->score;
  1359.       pbst = pnt;
  1360.       if (best > alpha) { alpha = best; }
  1361.       /* update best line */
  1362.       for (j = ply + 1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
  1363.       bstline[j] = 0;
  1364.       bstline[ply] = (node->f << 8) | node->t;
  1365.       /* if at the top */
  1366.       if (ply == 1)
  1367.         {
  1368.           /*
  1369.            * if its better than the root score make it
  1370.            * the root
  1371.            */
  1372.           if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)))
  1373.         {
  1374.           tmp = Tree[pnt];
  1375.           for (j = pnt - 1; j >= 0; j--) Tree[j + 1] = Tree[j];
  1376.           Tree[0] = tmp;
  1377.           pbst = 0;
  1378.         }
  1379.               if (Sdepth > 2)
  1380.                global_tmp_score = best;
  1381. #if !defined CHESSTOOL && !defined XBOARD
  1382. #ifdef QUIETBACKGROUND
  1383.           if (!background)
  1384. #endif /* QUIETBACKGROUND */
  1385.         if (Sdepth > 2)
  1386.           if (best > beta)
  1387.             {
  1388.               ShowResults (best, bstline, '+');
  1389. #ifdef DEBUG41
  1390.               debug41 (best, bstline, '+');
  1391. #endif
  1392.             }
  1393.           else if (best < alpha)
  1394.             {
  1395.               ShowResults (best, bstline, '-');
  1396. #ifdef DEBUG41
  1397.               debug41 (best, bstline, '-');
  1398. #endif
  1399.             }
  1400.           else
  1401.                    {
  1402.             ShowResults (best, bstline, '&');
  1403.                    }
  1404. #ifdef DEBUG41
  1405.           debug41 (best, bstline, '&');
  1406. #endif
  1407. #else
  1408.        if ((!background) && (Sdepth >2) && (best < alpha)){
  1409.             TCcount = 0;
  1410.         ExtraTime += 20*TCleft;
  1411.        }
  1412. #endif
  1413.         }
  1414.     }
  1415.       if (flag.timeout)
  1416.     {
  1417.           DepthBeyond-= extdb;
  1418. #if defined NULLMOVE || defined DEEPNULL
  1419.   PVari = PVarisave;
  1420. #endif
  1421.       return (Tscore[ply - 1]);
  1422.     }
  1423.     }
  1424.  
  1425.   /******************************************************************************************/
  1426.   node = &Tree[pbst];
  1427.   mv = (node->f << 8) | node->t;
  1428. #if defined NULLMOVE || defined DEEPNULL
  1429.   PVari = PVarisave;
  1430. #endif
  1431. #ifdef DEBUG
  1432. #include "debug512.h"
  1433. #endif
  1434.  
  1435.   /*
  1436.    * we have a move so put it in local table - if it's already there
  1437.    * done else if not there or needs to be updated also put it in
  1438.    * hashfile
  1439.    */
  1440. #if ttblsz
  1441. // remove the ply <= Sdepth check here as per Kong Sian
  1442.   if (SAVEHT && flag.hash /*&& ply <= Sdepth*/ && *rpt == 0 && best == alpha)
  1443.     {
  1444. #ifdef notdef
  1445. algbr(node->f,node->t,0);
  1446. /*printf("IN-> %lx %lx %d %d %s\n",hashkey,hashbd,depth,side,mvstr[0]);*/
  1447. #endif
  1448.       if (PutInTTable (side, best, depth, ply, alpha, beta, mv)
  1449. #ifdef HASHFILE
  1450.       && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  1451.     {
  1452. #ifdef notdef
  1453. /*printf("FT %d %d %d %x\n",side,best,depth,mv);*/
  1454. #endif
  1455.       PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t);
  1456.     }
  1457. #else
  1458.     );
  1459. #endif /* HASHFILE */
  1460.     }
  1461. #endif /* ttblsz */
  1462.   if (depth > 0)
  1463.     {
  1464. #ifdef HISTORY
  1465.       j = (node->f << 8) | node->t; // was 6 should be 8
  1466.       if (side == black)
  1467.     j |= 0x4000;
  1468.  
  1469. // above is a Kong Sian fix from after 4pl68
  1470.       if (history[j] < ((unsigned short) 1 << depth))
  1471.         history[j] = ((unsigned short) 1 << depth);
  1472. // below is original way
  1473. //      if (history[j] < HISTORYLIM)
  1474. //    history[j] += (unsigned short) 1<<depth;
  1475.  
  1476. #endif
  1477.       if (node->t != (short)(GameList[GameCnt].gmove & 0xFF))
  1478.     if (best <= beta)
  1479.       killr3[ply] = mv;
  1480.     else if (mv != killr1[ply])
  1481.       {
  1482.         killr2[ply] = killr1[ply];
  1483.         killr1[ply] = mv;
  1484.       }
  1485.       killr0[ply] = ((best > 9000) ? mv : 0);
  1486.     }
  1487.  
  1488.   DepthBeyond -= extdb; // this LINE added after 4pl68 by Kong Sian
  1489.  
  1490.   return (best);
  1491. }
  1492.  
  1493.  
  1494.  
  1495. int
  1496. castle (short side, short kf, short kt, short iop)
  1497.  
  1498. /* Make or Unmake a castling move. */
  1499.  
  1500. {
  1501.   register short rf, rt, t0, xside;
  1502.  
  1503.   xside = side ^ 1;
  1504.   if (kt > kf)
  1505.     {
  1506.       rf = kf + 3;
  1507.       rt = kt - 1;
  1508.     }
  1509.   else
  1510.     {
  1511.       rf = kf - 4;
  1512.       rt = kt + 1;
  1513.     }
  1514.   if (iop == 0)
  1515.     {
  1516.       if (kf != kingP[side] ||
  1517.       board[kf] != king ||
  1518.       board[rf] != rook ||
  1519.       color[kf] != side ||
  1520.       color[rf] != side ||
  1521.       Mvboard[kf] != 0 ||
  1522.       Mvboard[rf] != 0 ||
  1523.       color[kt] != neutral ||
  1524.       color[rt] != neutral ||
  1525.       color[kt - 1] != neutral ||
  1526.       SqAtakd3 (kf, xside) ||
  1527.       SqAtakd3 (kt, xside) ||
  1528.       SqAtakd3 (rt, xside))
  1529.     return (false);
  1530.     }
  1531.   else
  1532.     {
  1533.       if (iop == 1)
  1534.     {
  1535.           Castled[side] = 1;
  1536.       castld[side] = true;
  1537.       Mvboard[kf]++;
  1538.       Mvboard[rf]++;
  1539.     }
  1540.       else
  1541.     {
  1542.           Castled[side] = 0;
  1543.       castld[side] = false;
  1544.       Mvboard[kf]--;
  1545.       Mvboard[rf]--;
  1546.       t0 = kt;
  1547.       kt = kf;
  1548.       kf = t0;
  1549.       t0 = rt;
  1550.       rt = rf;
  1551.       rf = t0;
  1552.     }
  1553.       board[kt] = king;
  1554.       color[rt] = color[kt] = side;
  1555.       Pindex[kt] = 0;
  1556.       board[kf] = no_piece;
  1557.       color[rf] = color[kf] = neutral;
  1558.       board[rt] = rook;
  1559.       Pindex[rt] = Pindex[rf];
  1560.       board[rf] = no_piece;
  1561.       PieceList[side][Pindex[kt]] = kt;
  1562.       PieceList[side][Pindex[rt]] = rt;
  1563.       UpdateHashbd (side, king, kf, kt);
  1564.       UpdateHashbd (side, rook, rf, rt);
  1565.     }
  1566.   return (true);
  1567. }
  1568.  
  1569.  
  1570. void
  1571. EnPassant (short xside, short f, short t, short iop)
  1572.  
  1573. /*
  1574.  * Make or unmake an en passant move.
  1575.  */
  1576.  
  1577. {
  1578.   register short l;
  1579.  
  1580.   l = t + ((t > f) ? -8 : 8);
  1581.   if (iop == 1)
  1582.     {
  1583.       myEnPassant[xside] = 1;
  1584.       board[l] = no_piece;
  1585.       color[l] = neutral;
  1586.     }
  1587.   else
  1588.     {
  1589.       myEnPassant[xside] = 0;
  1590.       board[l] = pawn;
  1591.       color[l] = xside;
  1592.     }
  1593.   InitializeStats ();
  1594. }
  1595.  
  1596.  
  1597. void
  1598. UpdatePieceList (short side, short sq, short iop,short piece)
  1599.  
  1600. /*
  1601.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1602.  * capture is unmade.
  1603.  */
  1604.  
  1605. {
  1606.   register short i;
  1607.  
  1608.   if (iop == 1)
  1609.     {
  1610.       PieceCnt[side]--;
  1611.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1612.     {
  1613.       PieceList[side][i] = PieceList[side][i + 1];
  1614.       Pindex[PieceList[side][i]] = i;
  1615.     }
  1616.     }
  1617.   else
  1618.     { if(piece != king){
  1619.       PieceCnt[side]++;
  1620.       PieceList[side][PieceCnt[side]] = sq;
  1621.       Pindex[sq] = PieceCnt[side];
  1622.       } else {
  1623.     PieceCnt[side]++;
  1624.           for (i = PieceCnt[side]; i > 0; i--)
  1625.             {
  1626.               PieceList[side][i] = PieceList[side][i - 1];
  1627.               Pindex[PieceList[side][i]] = i;
  1628.             } 
  1629.         PieceList[side][0] = sq;
  1630.         Pindex[sq] = 0;
  1631.  
  1632.       }
  1633.     }
  1634. }
  1635.  
  1636. void
  1637. MakeMove (short side,
  1638.       struct leaf *node,
  1639.       short *tempb,    /* color of to square */
  1640.       short *tempc,    /* piece at to square */
  1641.       short *tempsf,    /* static value of piece on from */
  1642.       short *tempst,    /* static value of piece on to */
  1643.       short *INCscore)    /* score increment for pawn structure change */
  1644.  
  1645. /*
  1646.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1647.  * position obtained after making the move pointed to by node. Also update
  1648.  * miscellaneous stuff that changes when a move is made.
  1649.  */
  1650.  
  1651. {
  1652.   register short f, t, xside, ct, cf;
  1653.   register struct GameRec *g;
  1654.  
  1655.   xside = side ^ 1;
  1656.   g = &GameList[++GameCnt];
  1657.   g->hashkey = hashkey;
  1658.   g->hashbd = hashbd;
  1659.   g->epssq = epsquare;
  1660.   f = node->f;
  1661.   t = node->t;
  1662.   epsquare = -1;
  1663.   /* FROMsquare = f;*/
  1664.   TOsquare = t;
  1665.   *INCscore = 0;
  1666.   g->Game50 = Game50;
  1667.   g->gmove = (f << 8) | t;
  1668.   g->flags = node->flags;
  1669.   if (node->flags & cstlmask)
  1670.     {
  1671.       g->piece = no_piece;
  1672.       g->color = side;
  1673.       (void) castle (side, f, t, 1);
  1674.       Game50 = GameCnt;
  1675.     }
  1676.   else
  1677.     {
  1678.       if (!(node->flags & capture) && (board[f] != pawn))
  1679.     {
  1680.       rpthash[side][hashkey & 0xFF]++;
  1681.       ISZERO++;
  1682.     }
  1683.       else
  1684.     Game50 = GameCnt;
  1685.       *tempsf = svalue[f];
  1686.       *tempst = svalue[t];
  1687.       g->piece = *tempb = board[t];
  1688.       g->color = *tempc = color[t];
  1689.       if (*tempc != neutral)
  1690.     {
  1691.       UpdatePieceList (*tempc, t, 1,*tempb);
  1692.       /* if capture decrement pawn count */
  1693.       if (*tempb == pawn)
  1694.         {
  1695.           --PawnCnt[*tempc][column (t)];
  1696.         }
  1697.       if (board[f] == pawn)
  1698.         {
  1699.           cf = column (f);
  1700.           ct = column (t);
  1701.           /* move count from from to to */
  1702.           --PawnCnt[side][cf];
  1703.           ++PawnCnt[side][ct];
  1704.  
  1705.           /*
  1706.            * calculate increment for pawn structure
  1707.            * changes
  1708.            */
  1709.           /* doubled or more - */
  1710.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1711.         *INCscore -= 15;
  1712.           /* went to empty column + */
  1713.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1714.         *INCscore += 15;
  1715.  
  1716.           /*
  1717.            * went to outside col or empty col on one
  1718.            * side ????????
  1719.            */
  1720.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1721.         *INCscore -= 15;
  1722.         }
  1723.       mtl[xside] -= value[*tempb];
  1724.       if (*tempb == pawn)
  1725.         pmtl[xside] -= valueP;
  1726.       UpdateHashbd (xside, *tempb, -1, t);
  1727.       *INCscore += *tempst;
  1728.       Mvboard[t]++;
  1729.     }
  1730.       color[t] = color[f];
  1731.       board[t] = board[f];
  1732.       svalue[t] = svalue[f];
  1733.       Pindex[t] = Pindex[f];
  1734.       PieceList[side][Pindex[t]] = t;
  1735.       color[f] = neutral;
  1736.       board[f] = no_piece;
  1737.       if (board[t] == pawn)
  1738.     if (t - f == 16)
  1739.       epsquare = f + 8;
  1740.     else if (f - t == 16)
  1741.       epsquare = f - 8;
  1742.       if (node->flags & promote)
  1743.     {
  1744.       board[t] = node->flags & pmask;
  1745.       if (board[t] == queen)
  1746.         HasQueen[side]++;
  1747.       else if (board[t] == rook)
  1748.         HasRook[side]++;
  1749.       else if (board[t] == bishop)
  1750.         HasBishop[side]++;
  1751.       else if (board[t] == knight)
  1752.         HasKnight[side]++;
  1753.       --PawnCnt[side][column (t)];
  1754.       mtl[side] += value[board[t]] - valueP;
  1755.       pmtl[side] -= valueP;
  1756.       UpdateHashbd (side, pawn, f, -1);
  1757.       UpdateHashbd (side, board[t], f, -1);
  1758.       *INCscore -= *tempsf;
  1759.     }
  1760.       if (node->flags & epmask)
  1761.     EnPassant (xside, f, t, 1);
  1762.       else
  1763.     UpdateHashbd (side, board[t], f, t);
  1764.       Mvboard[f]++;
  1765.     }
  1766. }
  1767.  
  1768. void
  1769. UnmakeMove (short side,
  1770.         struct leaf *node,
  1771.         short *tempb, /* -> piece */
  1772.         short *tempc, /* -> side */
  1773.         short *tempsf,
  1774.         short *tempst)
  1775.  
  1776. /*
  1777.  * Take back a move.
  1778.  */
  1779.  
  1780. {
  1781.   register short f, t, xside;
  1782.  
  1783.   xside = side ^ 1;
  1784.   f = node->f;
  1785.   t = node->t;
  1786.   Game50 = GameList[GameCnt].Game50;
  1787.   if (node->flags & cstlmask)
  1788.     (void) castle (side, f, t, 2);
  1789.   else
  1790.     {
  1791.       color[f] = color[t];
  1792.       board[f] = board[t];
  1793.       svalue[f] = *tempsf;
  1794.       Pindex[f] = Pindex[t];
  1795.       PieceList[side][Pindex[f]] = f;
  1796.       color[t] = *tempc;
  1797.       board[t] = *tempb;
  1798.       svalue[t] = *tempst;
  1799.       if (node->flags & promote)
  1800.     {
  1801.       board[f] = pawn;
  1802.       ++PawnCnt[side][column (t)];
  1803.       mtl[side] += valueP - value[node->flags & pmask];
  1804.       pmtl[side] += valueP;
  1805.       UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1806.       UpdateHashbd (side, pawn, -1, t);
  1807.     }
  1808.       if (*tempc != neutral)
  1809.     {
  1810.       UpdatePieceList (*tempc, t, 2,*tempb);
  1811.       if (*tempb == pawn)
  1812.         {
  1813.           ++PawnCnt[*tempc][column (t)];
  1814.         }
  1815.       if (board[f] == pawn)
  1816.         {
  1817.           --PawnCnt[side][column (t)];
  1818.           ++PawnCnt[side][column (f)];
  1819.         }
  1820.       mtl[xside] += value[*tempb];
  1821.       if (*tempb == pawn)
  1822.         pmtl[xside] += valueP;
  1823.       UpdateHashbd (xside, *tempb, -1, t);
  1824.       Mvboard[t]--;
  1825.     }
  1826.       if (node->flags & epmask)
  1827.     {
  1828.       EnPassant (xside, f, t, 2);
  1829.     }
  1830.       else
  1831.     UpdateHashbd (side, board[f], f, t);
  1832.       Mvboard[f]--;
  1833.       if (!(node->flags & capture) && (board[f] != pawn))
  1834.     {
  1835.       rpthash[side][hashkey & 0xFF]--;
  1836.       ISZERO--;
  1837.     }
  1838.     }
  1839.   epsquare = GameList[GameCnt--].epssq;
  1840. }
  1841.  
  1842.  
  1843. void
  1844. InitializeStats (void)
  1845.  
  1846. /*
  1847.  * Scan thru the board seeing what's on each square. If a piece is found,
  1848.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1849.  * determine the material for each side and set the hashkey and hashbd
  1850.  * variables to represent the current board position. Array
  1851.  * PieceList[side][indx] contains the location of all the pieces of either
  1852.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1853.  * square.
  1854.  */
  1855.  
  1856. {
  1857.   register short i, sq;
  1858.  
  1859.   epsquare = -1;
  1860.   for (i = 0; i < 8; i++)
  1861.     {
  1862.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1863.     }
  1864.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1865.   PieceCnt[white] = PieceCnt[black] = 0;
  1866.   hashbd = hashkey = 0;
  1867.   for (sq = 0; sq < 64; sq++)
  1868.     if (color[sq] != neutral)
  1869.       {
  1870.     mtl[color[sq]] += value[board[sq]];
  1871.     if (board[sq] == pawn)
  1872.       {
  1873.         pmtl[color[sq]] += valueP;
  1874.         ++PawnCnt[color[sq]][column (sq)];
  1875.       }
  1876.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1877.  
  1878.     PieceList[color[sq]][Pindex[sq]] = sq;
  1879.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1880.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1881.       }
  1882. }
  1883.